package com.xiaolin.structure.queue.linked.doubleend;

/**
 * @ClassName DemoQueue
 * @Description 队列数据结构实现-根据双向链表实现
 * @Detail       说明：
 *                  1、队列空的条件： this.size == 0
 * @Author MyPC
 * @Date 2020/12/12
 * @Version 1.0
 */
public class DemoQueue<E> {
    // 队列个数
    private int size;
    // 队头元素
    private Node<E> front;
    // 队尾元素
    private Node<E> rear;

    /**
     * 索引校验
     */
    private void checkout(){
        if(size <=0){
            throw new IndexOutOfBoundsException("队列为空");
        }
    }

    /**
     * 向队尾添加元素,入队
     * @param e
     * @return
     */
    public boolean addLast(E e){
        if(size ==0){
            // 添加第一个元素时，队头元素与队尾元素是同一个
            front=new Node<>(e);
            rear=front;
        }else {
            // 关联新节点
            rear.next=new Node<>(e);
            rear.next.pre=rear;
            // 重新指定新的队尾元素
            rear=rear.next;
        }
        size++;
        return true;
    }

    /**
     * 从队头添加元素，入队
     * @param e
     * @return
     */
    public boolean addFirst(E e){
        if(size==0){
            //添加队列的第一个元素
            front=new Node<>(e);
            rear=front;
        }else {
            // 关联新元素
            front.pre=new Node<>(e);
            front.pre.next=front;
            //重新指定队头元素
            front=front.pre;
        }
        size++;
        return true;
    }

    /**
     * 从队头移除元素，出队
     * @return
     */
    public boolean removeFirst(){
        checkout();
        // 重新指定队头元素
        front=front.next;
        if(size == 1){
            // 移除最后一个元素，将rear置空
            rear=front;
        }else {
            // 不是移除最后一个元素，将新的队头元素的前驱节点置为null
            front.pre=null;
        }
        size--;
        return true;
    }

    /**
     * 从队尾移除元素，出队
     * @return
     */
    public boolean removeLast(){
        checkout();
        //重新指定队尾元素
        rear=rear.pre;
        if(size==1){
            front=rear;
        }else {
            rear.next=null;
        }
        size--;
        return true;
    }

    /**
     * 获取元素个数
     * @return
     */
    public int size(){
        return size;
    }

    /**
     * 获取第一个元素
     * @return
     */
    public E getFront(){
        checkout();
        return front.item;
    }

    /**
     * 获取最后一个元素
     * @return
     */
    public E getRear(){
        checkout();
        return rear.item;
    }
}
